package vector

import (
	"errors"
)

type Vector[T any] struct {
	data []T
	size int
	it   *Iterator[T]
}

const (
	default_cap = 3
)

type option struct {
	cap int
}

func AssignCapacity(capacity int) option {
	return option{
		cap: capacity,
	}
}
func New[T any](ops ...option) *Vector[T] {
	cap := default_cap
	for _, op := range ops {
		cap = op.cap
	}
	v := &Vector[T]{
		data: make([]T, 0, cap),
		size: 0,
	}
	return v
}

func (v *Vector[T]) PushBack(val T) {
	//自动扩容
	v.data = append(v.data, val)
	v.size++
}

func (v *Vector[T]) PopBack() {
	if v.size >= 1 {
		v.data = v.data[:v.size-1]
		v.size--
	}
}

func (v *Vector[T]) At(index int) (T, error) {
	if index < 0 || index >= v.size {
		return *new(T), errors.New("illegal indexes")
	}
	return v.data[index], nil
}

func (v *Vector[T]) Insert(vals ...T) {
	for _, val := range vals {
		v.PushBack(val)
	}
}

func (v *Vector[T]) InsertVector(other Vector[T]) {
	for _, val := range other.data {
		v.PushBack(val)
	}
}

func (v *Vector[T]) Clear() {
	size := len(v.data)
	v.data = make([]T, 0, size)
}
func (v *Vector[T]) EraseAt(index int) {
	if index >= v.size-1 {
		v.PopBack()
		return
	}
	prev := v.data[:index]
	suffix := v.data[index+1:]
	v.data = append(prev, suffix...)
	v.size = len(v.data)
}

func (v *Vector[T]) Size() int {
	return v.size
}

func (v *Vector[T]) Empty() bool {
	return v.Size() == 0
}

func (v *Vector[T]) Begin() *Iterator[T] {
	v.it = NewIterator(v)
	return v.it
}

func (v *Vector[T]) GetAtPtr(index int) *T {
	return &v.data[index]
}

func (v *Vector[T]) Front() (T, error) {
	val, err := v.At(0)
	if err == nil {
		return val, nil
	}
	return *new(T), err
}
func (v *Vector[T]) Back() (T, error) {
	val, err := v.At(v.size - 1)
	if err == nil {
		return val, nil
	}
	return *new(T), err
}
func (v *Vector[T]) FirstPtr() *T {
	if v.size >= 1 {
		return &v.data[0]
	}
	return nil
}
func (v *Vector[T]) BackPtr() *T {
	if v.size >= 1 {
		return &v.data[v.size-1]
	}
	return nil
}
